"use strict";

const util = require("util");
const axios = require("axios");

function format(items) {
  const data = {
    line: null,
    errors: null,
    message: null,
    other: null,
  };
  for (let i = 0; i < items.length; i++) {
    let item = items[i];
    if (i == 0) {
      data.line = item;
    } else if (item instanceof Error && item.stack) {
      if (data.errors === null) {
        data.errors = [];
      }
      data.errors.push(`${util.format(item)}==>${item.stack}`);
    } else if (typeof item === "string" && item.startsWith("{")) {
      try {
        data.message = JSON.parse(item);
      } catch (e) {
        if (data.other === null) {
          data.other = [];
        }
        data.other.push(item);
      }
    } else {
      if (data.other === null) {
        data.other = [];
      }
      data.other.push(item);
    }
  }
  return data;
}

/**
 *
 * For HTTP (browsers or node.js) use the following configuration params:
 *   {
 *      "type": "log4js-logstash-http-json",       // must be present for instantiation
 *      "application": "logstash-test",        // name of the application
 *      "logType": "application",        // type of the application
 *      "logChannel": "test",        // channel of the application
 *      "url": "http://lfs-server/_bulk",  // logstash receiver servlet URL
 *   }
 */
function logstashHTTPAppender(config) {
  const sender = axios.create({
    baseURL: config.url,
    timeout: config.timeout || 5000,
    headers: { "Content-Type": "application/json" },
    withCredentials: true,
  });

  return function log(event) {
    const data = format(event.data);
    const logstashEvent = {
      datetime: new Date(event.startTime).toISOString(),
      index: config.application,
      type: config.logType,
      channel: config.logChannel,
      level_name: event.level.levelStr,
      line: data.line,
      context: event.context,
    };
    if (data.errors) {
      logstashEvent.errors = data.errors;
    }
    if (data.message) {
      logstashEvent.message = data.message;
    }
    if (data.other) {
      logstashEvent.other = data.other;
    }
    const logstashJSON = JSON.stringify(logstashEvent);
    // send to server
    sender.post("", logstashJSON).catch((error) => {
      if (error.response) {
        console.error(
          `log4js.logstashHTTP Appender error posting to ${config.url}: ${
            error.response.status
          } - ${JSON.stringify(error.response.data)}`
        );
        return;
      }
      console.error(`log4js.logstashHTTP Appender error: ${error.message}`);
    });
  };
}

function configure(config) {
  return logstashHTTPAppender(config);
}

module.exports.configure = configure;
